package org.railage.client.gui.tabs;

import java.io.IOException;
import java.text.SimpleDateFormat;

import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTable;

import org.apache.log4j.Logger;
import org.railage.client.Client;
import org.railage.client.gui.main.GUI;
import org.railage.common.dto.TripDTO;

import javax.swing.JScrollPane;
import javax.swing.table.DefaultTableModel;

import java.awt.event.ActionListener;
import java.awt.event.ActionEvent;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;

import javax.swing.DefaultComboBoxModel;
import javax.swing.JButton;
import javax.swing.JTextPane;
import javax.swing.SpinnerDateModel;
import javax.swing.SpinnerNumberModel;
import javax.swing.UIManager;
import javax.swing.JComboBox;
import javax.swing.JSpinner;

public class EditTripsTab extends AbstractTab {

	private static final long serialVersionUID = -3404641839514507539L;

	private static final Logger log = Logger.getLogger(EditTripsTab.class);

	private static final String SELECT_ROUTE = "-- Select route --";
	private static final String DELETE_CONFIRM_TITLE = "Trip delete confirmation";

	private static final int SEATS_DEFAULT = 100;
	private static final int SEATS_MIN = 0;
	private static final int SEATS_MAX = 5000;
	private static final int SEATS_STEP = 1;

	private SimpleDateFormat dateTimeFormatter = new SimpleDateFormat(
			GUI.DATE_FORMAT + " " + GUI.TIME_FORMAT);

	private String[] routes = null;
	private String[] columnNames = new String[] { "Start", "Trip ID", "Route",
			"Total seats" };

	private JSpinner seatsNumberField;
	private JSpinner startTimestampField;
	private JComboBox<String> routeNameBox;
	private JTable tripsTable;

	public EditTripsTab() {
		setLayout(null);

		JTextPane info = new JTextPane();
		info.setBackground(UIManager.getColor("Panel.background"));
		info.setText("To add new trip select route name, seats number and start date and time.\r\n\r\nTo delete existing route double-click it in the list.");
		info.setBounds(10, 11, 262, 69);
		add(info);

		JLabel lblRoute = new JLabel("Route name");
		lblRoute.setBounds(10, 121, 86, 14);
		add(lblRoute);

		routeNameBox = new JComboBox<String>();
		routeNameBox.setBounds(121, 118, 151, 20);
		add(routeNameBox);

		JLabel lblSeatsNumber = new JLabel("Seats number");
		lblSeatsNumber.setBounds(10, 155, 101, 14);
		add(lblSeatsNumber);

		seatsNumberField = new JSpinner(new SpinnerNumberModel(SEATS_DEFAULT,
				SEATS_MIN, SEATS_MAX, SEATS_STEP));
		seatsNumberField.setBounds(121, 152, 151, 20);
		add(seatsNumberField);

		JLabel lblStartDate = new JLabel("Start date & time");
		lblStartDate.setBounds(10, 186, 101, 14);
		add(lblStartDate);

		startTimestampField = new JSpinner(new SpinnerDateModel());
		JSpinner.DateEditor startTimestampFieldEditor = new JSpinner.DateEditor(
				startTimestampField, GUI.DATE_FORMAT + " " + GUI.TIME_FORMAT);
		startTimestampField.setEditor(startTimestampFieldEditor);
		startTimestampField.setBounds(121, 183, 151, 20);
		add(startTimestampField);

		JButton btnAdd = new JButton("Add");
		btnAdd.addActionListener(new ActionListener() {
			public void actionPerformed(ActionEvent e) {
				addTrip();
			}
		});
		btnAdd.setBounds(183, 214, 89, 23);
		add(btnAdd);

		JScrollPane scrollPane = new JScrollPane();
		scrollPane.setBounds(282, 0, 438, 390);
		add(scrollPane);

		tripsTable = new JTable();
		tripsTable.addMouseListener(new MouseAdapter() {
			public void mouseClicked(MouseEvent e) {
				if (e.getClickCount() == 2) {
					int row = tripsTable.rowAtPoint(e.getPoint());
					int tripID = (Integer) tripsTable.getValueAt(row, 1);
					deleteTrip(tripID);
				}
			}
		});
		scrollPane.setViewportView(tripsTable);
	}

	public void init() {
		fillTable();
		fillRoutesComboBox();
	}

	private void fillRoutesComboBox() {
		try {
			routes = (String[]) Client.getInstance().callMethod(
					"getRouteNames", null);
			String[] items = new String[routes.length + 1];
			items[0] = SELECT_ROUTE;
			System.arraycopy(routes, 0, items, 1, routes.length);

			routeNameBox.setModel(new DefaultComboBoxModel<String>(items));
		} catch (IOException e) {
			log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
			JOptionPane.showMessageDialog(this, GUI.DISCON_UNEXP_GUI_MSG);
		}
	}

	private void fillTable() {
		Object[][] data = new Object[][] {};
		TripDTO[] trips = null;
		try {
			trips = (TripDTO[]) Client.getInstance().callMethod("getAllTrips",
					null);
			data = new Object[trips.length][];
			int i = 0;
			for (TripDTO trip : trips) {
				data[i] = new Object[] {
						dateTimeFormatter.format(trip.getStart()),
						trip.getId(), trip.getRouteName(), trip.getSeats() };
				i++;
			}
		} catch (IOException e) {
			log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
			JOptionPane.showMessageDialog(this, GUI.DISCON_UNEXP_GUI_MSG);
		}
		tripsTable.setModel(new DefaultTableModel(data, columnNames) {
			private static final long serialVersionUID = -7584952328807090039L;

			@Override
			public boolean isCellEditable(int row, int column) {
				return false;
			}
		});
		tripsTable.getColumnModel().getColumn(0).setPreferredWidth(180);
		tripsTable.getColumnModel().getColumn(1).setPreferredWidth(90);
		tripsTable.getColumnModel().getColumn(2).setPreferredWidth(230);
		tripsTable.getColumnModel().getColumn(3).setPreferredWidth(100);
	}

	private void addTrip() {
		Object request = new Object[] { routeNameBox.getSelectedItem(),
				(Integer) seatsNumberField.getValue(),
				dateTimeFormatter.format(startTimestampField.getValue()) };
		String result = null;
		try {
			result = (String) Client.getInstance().callMethod("addTrip",
					request);
			if (!result.equals("Trip added")) {
				JOptionPane.showMessageDialog(this, result);
			}
		} catch (IOException e) {
			log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
			JOptionPane.showMessageDialog(this, GUI.DISCON_UNEXP_GUI_MSG);
		}
		fillTable();
	}

	private void deleteTrip(int tripID) {
		int confirmed = JOptionPane.showConfirmDialog(this,
				"Are you sure you want to delete trip #" + tripID + "?",
				DELETE_CONFIRM_TITLE, JOptionPane.YES_NO_OPTION);
		if (confirmed == 0) {
			String result = null;
			try {
				result = (String) Client.getInstance().callMethod("deleteTrip",
						tripID);
				if (!result.equals("Trip deleted")) {
					JOptionPane.showMessageDialog(this, result);
				}
			} catch (IOException e) {
				log.error(GUI.DISCON_UNEXP_LOG_MSG, e);
				JOptionPane.showMessageDialog(this, GUI.DISCON_UNEXP_GUI_MSG);
			}
			fillTable();
		}
	}
}
